package com.ultrawise.survey.core.base;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.stereotype.Repository;

import com.ultrawise.survey.common.printfile.EntityObjectValues;
import com.ultrawise.survey.common.utils.SQLUtils;
import com.ultrawise.survey.core.Page;
import com.ultrawise.survey.core.PaginationHelper;

/**
 * dao 的基类
 */
@SuppressWarnings("all")
@Repository("baseDao")
public class BaseDao extends JdbcDaoSupport {

	public Object getMaxId(Saveable objForSave) {
		String sql = "select max(id) from " + objForSave.getTableName() + "";
		return getJdbcTemplate().queryForInt(sql);
	}

	public Object getMaxID(Saveable objForSave) {
		String sql = "select max(" + objForSave.getKeyColumns()[0] + ") from "
				+ objForSave.getTableName() + "";
		return getJdbcTemplate().queryForInt(sql);
	}

	public Object getMaxByColname(Saveable objForSave, String colname) {
		String sql = "select max(" + colname + ") from "
				+ objForSave.getTableName() + "";
		return getJdbcTemplate().queryForInt(sql);
	}

	public int delete(Object id, Saveable objForSave) {
		String sql = "delete from " + objForSave.getTableName() + " where "
				+ objForSave.getKeyColumns()[0] + "=?";
		// 增加业务日志信息
		// setLogNoUpdate(CyapConstants.LOGBUSINESS_TYPE_DELETE, objForSave,
		// id);
		return getJdbcTemplate().update(sql, new Object[] { id });
	}

	public List findAll(Saveable objForSave, Class obj) {
		String sql = "select * from " + objForSave.getTableName();
		return getJdbcTemplate().query(sql, new BeanPropertyRowMapper(obj));
	}

	public List findAll(Saveable objForSave, Class obj, String orderby) {
		String sql = "select * from " + objForSave.getTableName() + orderby;
		return getJdbcTemplate().query(sql, new BeanPropertyRowMapper(obj));
	}

	public Object findByID(Object id, Saveable objForSave, Class obj) {
		String sql = "select * from " + objForSave.getTableName() + " where "
				+ objForSave.getKeyColumns()[0] + "=?";
		return getJdbcTemplate().queryForObject(sql, new Object[] { id },
				new BeanPropertyRowMapper(obj));
	}

	public Object findByColunmObj(final Object colunm, final Object value,
			final Saveable objForSave, final Class obj) throws DaoException {
		return queryNullAble(new JdbcTemplateCallBack<Object>() {
			public Object querys(JdbcTemplate jdbcTemplate) {
				String sql = "select * from " + objForSave.getTableName()
						+ " where " + colunm + "=?";
				return jdbcTemplate.queryForObject(sql, new Object[] { value },
						new BeanPropertyRowMapper(obj));

			}
		});
	}

	public Object findByColunmObj2(final Object colunm, final Object value,
			final Object colunm2, final Object value2,
			final Saveable objForSave, final Class obj) throws DaoException {
		return queryNullAble(new JdbcTemplateCallBack<Object>() {
			public Object querys(JdbcTemplate jdbcTemplate) {
				String sql = "select * from " + objForSave.getTableName()
						+ " where " + colunm + "=? and " + colunm2 + "=?";
				return jdbcTemplate.queryForObject(sql, new Object[] { value,
						value2 }, new BeanPropertyRowMapper(obj));
				// return
				// jdbcTemplate.queryForObject("select *  from am_book_caseverify where "+columnName+"=?",
				// new
				// BeanPropertyRowMapper(AmBookCaseVerify.class),value);
			}
		});
	}

	public List findByColunm(String colunm, String value, Saveable objForSave,
			Class obj) {
		String sql = "select * from " + objForSave.getTableName() + " where "
				+ colunm + "=? ";
		return getJdbcTemplate().query(sql, new BeanPropertyRowMapper(obj),
				value);
	}

	/*
	 * 这里用的Database的主键自增策略，如果想自己实现可以去看看Hibernate的主键生成方法
	 * 其实简单一点可以在server起来的时候定义一个存放主键的Map,然后让这些主键值递增就可以了， 只是要注意一下并发问题
	 */
	public int insert(Saveable objForSave) {
		int newid =0;
		try{
		Object[] sqlAndParams = SQLUtils.generateInsert(objForSave,
				objForSave.getTableName());
		String objname = objForSave.getClass().getSimpleName();
		// 新增加数据获取 执行成功的记录数
		 getJdbcTemplate().update((String) sqlAndParams[0],
				(Object[]) sqlAndParams[1]);
		 
		  newid =  getJdbcTemplate().queryForInt( 
				  "select LAST_INSERT_ID() AS id"); 
		}catch(Exception e){
			e.printStackTrace();
		}
		return newid;
	}

	@SuppressWarnings("unchecked")
	public int update(Saveable objForSave) {
		Object[] sqlAndParams = SQLUtils.generateUpdate(objForSave,
				objForSave.getTableName(), objForSave.getKeyColumns()[0]);
		// 增加业务日志信息
		Class obclass = objForSave.getClass();
		Object[] parmarray = (Object[]) sqlAndParams[1];
		Object objfront = findByID(parmarray[(parmarray.length) - 1],
				objForSave, obclass);
		int count = getJdbcTemplate().update((String) sqlAndParams[0],
				(Object[]) sqlAndParams[1]);
		return count;
	}

	/**
	 * 添加 ，属性和数据库字段名一致，返回主键
	 * 
	 * @param objForSave
	 *            ,继承Saveable 的接口的类
	 * @return
	 */
	public Number saveAndReturnKey(Saveable objForSave) {
		return saveAndReturnKey(objForSave, objForSave.getTableName(),
				objForSave.getKeyColumns());
	}

	/**
	 * 添加实体,返回主键
	 * 
	 * @param objForSave
	 * @param tableName
	 * @param columnAndValue
	 * @param keyColumns
	 * @return
	 */
	public Number saveAndReturnKey(Object objForSave, String tableName,
			String... keyColumns) {
		SimpleJdbcInsert insertActor = getSimpleJdbcInsert();
		insertActor.setTableName(tableName);
		insertActor.usingGeneratedKeyColumns(keyColumns);
		Number newId = insertActor
				.executeAndReturnKey(new BeanPropertySqlParameterSource(
						objForSave));
		traceSql(insertActor.getInsertString());

		// 增加业务日志信息
		// setLogNoUpdate(CyapConstants.LOGBUSINESS_TYPE_CREATE, objForSave,
		// newId);
		return newId;
	}

	/**
	 * @param objForSave
	 *            插入数据库的类
	 * @param tableName
	 * @param keyColumns
	 * @return
	 */
	public void save(Saveable objForSave) {
		SimpleJdbcInsert insertActor = getSimpleJdbcInsert();
		insertActor.setTableName(objForSave.getTableName());
		insertActor.execute(new BeanPropertySqlParameterSource(objForSave));
		traceSql(insertActor.getInsertString());
	}

	/**
	 * @param objForSave
	 *            插入数据库的类，注意
	 * @param tableName
	 * @param keyColumns
	 * @return
	 */
	public void save(Object objForSave, String tableName) {
		SimpleJdbcInsert insertActor = getSimpleJdbcInsert();
		insertActor.setTableName(tableName);
		insertActor.execute(new BeanPropertySqlParameterSource(objForSave));
		traceSql(insertActor.getInsertString());
	}

	/**
	 * 
	 * @param objForSave
	 *            插入数据库的类
	 * @param tableName
	 * @param keyColumns
	 * @return
	 */
	public void save(Object objForSave, String tableName, String... keyColumns) {
		SimpleJdbcInsert insertActor = getSimpleJdbcInsert();
		insertActor.setTableName(tableName);
		insertActor.execute(new BeanPropertySqlParameterSource(objForSave));
		traceSql(insertActor.getInsertString());
	}

	/** */
	/**
	 * 可以用于处理查询queryfor
	 * 为空或者多条的时候返回异常的情况，现在返回null,主要是拦截IncorrectResultSizeDataAccessException异常
	 * ,以及子类
	 * 
	 * @param jdbcTemplateCallBack
	 * @return
	 * @throws DaoException
	 */
	public <T> T queryNullAble(JdbcTemplateCallBack<T> jdbcTemplateCallBack)
			throws DaoException {
		try {
			return jdbcTemplateCallBack.querys(getJdbcTemplate());
		} catch (Exception e) {
			if ((e instanceof IncorrectResultSizeDataAccessException)
					&& ((IncorrectResultSizeDataAccessException) e)
							.getActualSize() == 0)
				return null;
			// 其他的异常正常抛出
			throw new DaoException(e);
		}
	}

	// 根据条件查询数据

	public Page searchAllData(Map codeMap, Map<String, String> map,
			String acStatus, Saveable objForSave, final Class obj,
			final int pageNo, final int pageSize) throws DaoException {
		PaginationHelper ph = new PaginationHelper();
		String sql = "from " + objForSave.getTableName() + " a where 1=1";
		Object[] params = new Object[map.size() + 1];
		int index = 0;
		if (!StringUtils.isEmpty(acStatus)) {
			sql = "from "
					+ objForSave.getTableName()
					+ " a,am_info_case b where 1=1 and a.ac_code = b.ac_code and b.ac_status != ? ";
			params[index] = acStatus;
			index++;
		}
		for (Iterator keys = map.keySet().iterator(); keys.hasNext();) {
			String key = (String) keys.next();
			if (key.equals("startTime")) {
				sql += " and datediff(day, a.createtime, ?) <= 0 ";
				params[index] = map.get(key);
				index++;
			} else if (key.equals("endTime")) {
				sql += " and datediff(day, a.createtime, ?) >= 0 ";
				params[index] = map.get(key);
				index++;
			} else if (key.contains("Code")) {
				sql += " and a." + key + " = ? ";
				params[index] = map.get(key);
				index++;
			} else if (key.equals("sv_Checkman")) {
				sql += " and a." + key + " = ? ";
				params[index] = map.get(key);
				index++;
			} else {
				sql += " and a." + key + " like ? ";
				params[index] = "%" + map.get(key) + "%";
				index++;
			}
		}
		if (codeMap != null && codeMap.size() > 0) {
			// sql += " or a.ac_code in ("
			// + com.hwadee.cyap.common.StringUtils.join2ByMapkey(codeMap,
			// ",") + ") ";
		}
		Object[] paramsEnd = new Object[index];
		System.arraycopy(params, 0, paramsEnd, 0, index);
		return ph.fetchPage(getJdbcTemplate(), "select count(*) " + sql,
				"select a.* " + sql, paramsEnd, pageNo, pageSize,
				new BeanPropertyRowMapper(obj));
	}

	/**对数据库简化
	 * 
	 * @param objForSave
	 * @param tableName
	 * @param columnAndValue
	 * @param keyColumns
	 * @return
	 */
	public Number saveAndReturnKey(String tableName,
			Map<String, Object> columnAndValue, String... keyColumns) {
		SimpleJdbcInsert insertActor = getSimpleJdbcInsert();
		insertActor.setTableName(tableName);
		insertActor.usingGeneratedKeyColumns(keyColumns);
		Number newId = insertActor.executeAndReturnKey(columnAndValue);
		traceSql(insertActor.getInsertString());
		return newId;
	}

	public NamedParameterJdbcTemplate getNamedParameterJdbcTemplate() {
		return new NamedParameterJdbcTemplate(getJdbcTemplate());
	}

	// ----tools
	public SimpleJdbcInsert getSimpleJdbcInsert() {
		return new SimpleJdbcInsert(getJdbcTemplate());
	}

	public SimpleJdbcInsert getSimpleJdbcInsert(String tableName) {
		return new SimpleJdbcInsert(getJdbcTemplate());
	}

	public void traceSql(String sql) {
		LogInfo.logger.info("JDBC:" + sql);
	}

	/****
	 * 判断对象是否在不记录日志的表中
	 * 
	 * @param obj
	 * @return
	 */
	private boolean filterNotTableName(Object obj) {
		String objtabname = (String) EntityObjectValues.getFieldVlaue(obj,
				"TABLENAME");
		// 表示在不记录日志信息的表中
		// if (CdformConstants.NOT_BUEINESS_LOG_TABLENAME.get(objtabname) !=
		// null)
		// return true;
		return false;
	}

	public void execute(String ddlsql)throws DataAccessException {
		this.getJdbcTemplate().execute(ddlsql);
	}
	
	
	/***
	 * 根据sql执行返回一个list对象集合，集合内容为map
	 * @param sql
	 * @return
	 */
	public List<Map<String,Object>> queryBysql(String sql){
//		System.out.println("aaaaa");
		return this.getJdbcTemplate().queryForList(sql);
	}

}
